#include <iostream>
#include <string>
#include <map>
#include "../video.hpp"
#include "../../../libpland/lib/plugin.hpp"
#include <unistd.h>
#include <stdlib.h>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>

using namespace std;

using namespace pland;

class Encoder : public UserC_Plugin
{
public:
    Encoder();
    ~Encoder();
    void start();
    void stop();
    void load_queues(SharedDQueue front ,SharedDQueue back);
    void setId(int id);
private:
    SharedDQueue front_;
    SharedDQueue back_;
    bool running_;
    int id_;
};


Encoder::Encoder()
{
    running_ = false;
}

Encoder::~Encoder()
{
}

void Encoder::setId(int id)
{
    id_ = id;
}

void Encoder::start()
{
    utill_log("Pluggin Encoder Started ID:" + utill_to_string(id_));
    running_ = true;
    while(running_)
    {
        SharedData source = front_->pop();
        if(!isImgTag(source->get_header()->tag))
        {
            back_->push(source);
            continue;
        }
        try
        {
            int rows = *((uint32_t*)(source->get_data()));
            int cols = (source->get_header()->size - sizeof(uint32_t))/rows;
            cv::Mat img(rows, cols, CV_8U, ((char*)source->get_data()) + sizeof(uint32_t));
            std::vector <uchar> png;
            cv::imencode(".png", img, png, std::vector<int>());
            char* data = new char[png.size()];
            ::memcpy(data, png.data(), png.size());

            Data_Header *h = new Data_Header;
            ::memcpy(h,source->get_header(), sizeof(Data_Header));
            h->size = png.size();
            switch(h->tag)
            {
            case IMG_TAG_B:
                h->tag = PNG_TAG_B;
                break;
            case IMG_TAG_G:
                h->tag = PNG_TAG_G;
                break;
            case IMG_TAG_R:
                h->tag = PNG_TAG_R;
                break;
            }
            SharedData item(new Data(data, h));
            back_->push(item);
        }
        catch(cv::Exception &e)
        {
            continue;
        }
    }
}

void Encoder::stop()
{
    running_ = false;
}

void Encoder::load_queues(SharedDQueue front ,SharedDQueue back)
{
    front_  = front;
    back_  = back;
}


extern "C"
{

UserC_Plugin* Core_GetInstance()
{
    return new Encoder();
}

void Core_KillInstance(UserC_Plugin* a)
{
    delete dynamic_cast<Encoder*>(a);
}

}
